import React from 'react'
import PropTypes from 'prop-types'
import { isEqual } from 'lodash'
import { Responsive } from 'react-grid-layout'
import 'react-grid-layout/css/styles'
import 'react-resizable/css/styles'
import configs from '@/modules/mapping'
import WidthProvider from './customWidthProvider'
import Card from '../card'
import * as gridConfig from './props/cardGrid'

const findOrGenerateResponsiveLayout = Responsive.utils.findOrGenerateResponsiveLayout
const ResponsiveGridLayout = WidthProvider(Responsive)

class CardGrid extends React.Component {
  static defaultProps = { ...gridConfig }
  constructor(props) {
    super(props)
    const { breakpoints = { lg: 1200 }, layouts } = props
    const currentLayout = findOrGenerateResponsiveLayout(layouts, breakpoints)

    this.state = {
      currentLayout,
      layouts,
      breakpoints,
      popCard: ''
    }
  }

  static getDerivedStateFromProps(nextProps, prevState) {
    if (nextProps) {
      const { breakpoints = { lg: 1200 }, layouts } = nextProps
      const currentLayout = findOrGenerateResponsiveLayout(layouts, breakpoints)
      return {
        currentLayout,
        layouts,
        breakpoints
      }
    }
    return null
  }

  onLayoutChange = (currentLayout, allLayouts) => {
    if (typeof this.props.onLayoutChange === 'function') {
      this.props.onLayoutChange(currentLayout, allLayouts)
    }
    this.setState({
      currentLayout,
      layouts: allLayouts
    })
  }

  onResizeStop = (layout, oldItem, newItem, placeholder, e, element) => {
    if (typeof this.props.onResizeStop === 'function') {
      if (!isEqual(oldItem, newItem)) {
        this.props.onResizeStop(layout, oldItem, newItem, placeholder, e, element)
      }
    }
  }

  onDragStop = (layout, oldItem, newItem, placeholder, e, element) => {
    if (typeof this.props.onDragStop === 'function') {
      if (!isEqual(oldItem, newItem)) {
        this.props.onDragStop(layout, oldItem, newItem, placeholder, e, element)
      }
    }
  }

  render() {
    const { cards, commonFiltersObject, autoLoad, ...rest } = this.props
    const { breakpoints, layouts, currentLayout, popCard } = this.state
    const cardOperationProps = this.getCardOperationProps()
    // layouts必须要有lg的配置
    if (!layouts.lg) {
      return null
    }
    return (
      <ResponsiveGridLayout
        {...rest}
        layouts={layouts}
        breakpoints={breakpoints}
        onLayoutChange={this.onLayoutChange}
        onResizeStop={this.onResizeStop}
        onDragStop={this.onDragStop}>
        {currentLayout.map(({ i, w }) => {
          const card = cards[i]
          if (card) {
            const { cid = i, className = '', type } = card
            const isPop = popCard === cid ? 'popCard .cancelDrag' : ''
            let configProps = ''
            if (configs[type]) {
              configProps = {
                ...configs[type],
                title: card.name || configs[type].name,
                currentFilters: configs[type].filters
              }
            }
            return (
              <div id={cid} key={cid} className={`cardGridWrapper ${className} ${isPop}`}>
                <Card
                  {...card}
                  {...configProps}
                  cid={cid}
                  commonFiltersObject={commonFiltersObject}
                  {...cardOperationProps}
                  width={w}
                  isPop={isPop}
                />
              </div>
            )
          }
          return <div className="cardGridWrapper" key={i}></div>
        })}
      </ResponsiveGridLayout>
    )
  }
}

CardGrid.propTypes = {
  margin: PropTypes.array,
  containerPadding: PropTypes.array,
  isDraggable: PropTypes.bool,
  isResizable: PropTypes.bool,

  cards: PropTypes.object,
  layouts: PropTypes.object,
  onLayoutChange: PropTypes.func,
  onResizeStop: PropTypes.func,
  onDragStop: PropTypes.func,
  breakpoints: PropTypes.object,
  onDeleteCard: PropTypes.func,
  onUpdateCardConfig: PropTypes.func,
  rowHeight: PropTypes.number,
  draggableHandle: PropTypes.string,
  draggableCancle: PropTypes.string
}
